

#include "unity.h"
#include "unity_fixture.h"

#include "BSP_Sleep.h"

#include "Reader.h"
#include "phNfcLib_Initialization.h"

#include "ISO7816/i7816_activate.h"
#include "ISO7816/i7816_log.h"
#include "ISO7816/i7816.h"
#include "Reader/reader_samav3.h"
/*============================================================*/
extern phhalHw_SamAV3_DataParams_t stHal_SamAv3;

int desfire_main(void);
int wavelynx_main(void);

static void samav3_print_key_entry_read(const key_entry_read_t* key_entry){
	LOG2_INF("\nkey_entry_read:\n");
	LOG2_PRINT("key_ver: %02X,%02X,%02X\n", key_entry->ver[0], key_entry->ver[1], key_entry->ver[2]);
	LOG2_PRINT("aid: %02X%02X%02X\n", key_entry->aid[0], key_entry->aid[1], key_entry->aid[2]);
	LOG2_PRINT("key_no: %02X\n", key_entry->key_no);
	LOG2_PRINT("key_no_cek: %02X\n", key_entry->key_no_cek);
	LOG2_PRINT("key_v_cek: %02X\n", key_entry->key_v_cek);
	LOG2_PRINT("ref_no_kuc: %02X\n", key_entry->ref_no_kuc);
	LOG2_PRINT("set: %04X\n", key_entry->set);
	LOG2_PRINT("ext_set: %04X\n", key_entry->ext_set);
	LOG2_PRINT("key_no_aek: %02X\n", key_entry->key_no_aek);
	LOG2_PRINT("key_v_aek: %02X\n", key_entry->key_v_aek);
	LOG2_PRINT("\n");
}

/*============================================================*/

TEST_GROUP(SAMAV3);


TEST_SETUP(SAMAV3)
{
	
}

TEST_TEAR_DOWN(SAMAV3)
{
	
}


#if 0
TEST(SAMAV3, DesfireReadWrite)
{
	desfire_main();
}
#endif 

#if 0
TEST(SAMAV3, ReadWaveLynx)
{
	wavelynx_main();
}
#endif 

#if 0
TEST(SAMAV3, loadkey)
{
	uint8_t kid = SAM_KID_APPLE_PRIV;
	int ret = samav3_init();
	TEST_ASSERT_EQUAL_INT(0, ret);	
	ret = samav3_activate();
	TEST_ASSERT_EQUAL_INT(0, ret);
	// key_entry_read_t key_entry_default;
	// uint8_t val[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x20,0x02,0x00,0x00,0xFF,0xFF};
	// memcpy(&key_entry_default, val, sizeof(key_entry_default));
	// samav3_print_key_entry_read(&key_entry_default);
	//读取密钥
	key_entry_read_t key_entry;
	ret = samav3_get_key_entry(kid, &key_entry);
	TEST_ASSERT_EQUAL_INT(0, ret);
	LOG2_BUF_INF("key_entry_read", (uint8_t*)&key_entry, sizeof(key_entry));
	samav3_print_key_entry_read(&key_entry);
#if 1
	//装载密钥
	uint8_t key[16] = {1};
	ret = samav3_load_key(SAM_KID_APPLE_PRIV, key, 1, SAM_KEY_CLASS_OfflineCrypto, SAM_KEY_T_AES_128, 1);
	TEST_ASSERT_EQUAL_INT(0, ret);
	ret = samav3_get_key_entry(SAM_KID_APPLE_PRIV, &key_entry);
	TEST_ASSERT_EQUAL_INT(0, ret);
	LOG2_BUF_INF("key_entry_read", (uint8_t*)&key_entry, sizeof(key_entry));
	samav3_print_key_entry_read(&key_entry);
	//恢复默认密钥
	ret = samav3_disable_key_entry(SAM_KID_APPLE_PRIV);
	TEST_ASSERT_EQUAL_INT(0, ret);
	ret = samav3_get_key_entry(SAM_KID_APPLE_PRIV, &key_entry);
	TEST_ASSERT_EQUAL_INT(0, ret);
	LOG2_BUF_INF("key_entry_read", (uint8_t*)&key_entry, sizeof(key_entry));
	samav3_print_key_entry_read(&key_entry);
#endif 
	//下电
	ret = samav3_deactivate();
	TEST_ASSERT_EQUAL_INT(0, ret);
}
#endif 

//	int samav3_init2(void);

#if 0
 TEST(SAMAV3, init2)
 {
 	LOG2_INF("wait key:");
	SEGGER_RTT_WaitKey();
	uint8_t kid = SAM_KID_APPLE_PRIV;
	int ret = samav3_init2();
	TEST_ASSERT_EQUAL_INT(0, ret);
	//下电
	ret = samav3_deactivate();
	TEST_ASSERT_EQUAL_INT(0, ret);
	//上电
	ret = samav3_activate2();
	TEST_ASSERT_EQUAL_INT(0, ret);
 }
#endif 

#if 0
TEST(SAMAV3, pre_perso)
{
	uint8_t kid = 0;
	int ret = samav3_init2();
	TEST_ASSERT_EQUAL_INT(0, ret);	
//		ret = samav3_activate();
//		TEST_ASSERT_EQUAL_INT(0, ret);	
	//读取密钥
	key_entry_read_t key_entry_read;

	while(1){
		LOG2_PRINT("wait key: \n");
		int input = SEGGER_RTT_WaitKey();
		LOG2_PRINT("input: %c\n", input);
		switch(input){
		case '0':{
			kid = 0;
			sam_key_entry_t sam_key_entry = {
				.keys[0] = {0x01,},
				.keys[1] = {0x11,},
				.keys[2] = {0x22,},
				.key_ver[0] = 0,
				.key_ver[1] = 1,
				.key_ver[2] = 2,
				.kce_no = 0xFE,		//不需要认证
				.set = 0x0020,
				.kae_no = 0xFE,
				.kae_ver = 0xFF,
				.kuc_no = 0xFF,
			};
			ret = samav3_change_key_entry(kid, &sam_key_entry);
			if(ret){
				LOG2_ERR("samav3_change_key_entry fail: %04X", ret);
				break;
			}
			ret = samav3_get_key_entry(kid, &key_entry_read);
			if(ret){
				LOG2_ERR("samav3_get_key_entry fail: %04X", ret);
				break;
			}
			samav3_print_key_entry_read(&key_entry_read);
		}
		break;
		case '1':{
			kid = 0;
			sam_key_entry_t sam_key_entry = {
				.keys[0] = {0x00,},
				.keys[1] = {0x00,},
				.keys[2] = {0x00,},
				.key_ver[0] = 0,
				.key_ver[1] = 0,
				.key_ver[2] = 0,
				.kce_no = 0,
				.kce_ver = 0,
				.set = 0x0020,
				.ext_set = 0x0000,
				.kuc_no = 0xFF,
				.kae_no = 0xFE,
				.kae_ver = 0xFF,
			};
			ret = samav3_change_key_entry(kid, &sam_key_entry);
			if(ret){
				LOG2_ERR("samav3_change_key_entry fail: %04X", ret);
				break;
			}
			
			ret = samav3_get_key_entry(kid, &key_entry_read);
			if(ret){
				LOG2_ERR("samav3_get_key_entry fail: %04X", ret);
				break;
			}
			samav3_print_key_entry_read(&key_entry_read);

		}
		break;
		case '2':{
			phKeyStore_Sw_DataParams_t * pKeyStore = phNfcLib_GetDataParams(PH_COMP_KEYSTORE);
			phStatus_t status;
			uint8_t master_key[16] = {0x00, };
			status = phKeyStore_FormatKeyEntry(pKeyStore, 0x00, PH_CRYPTOSYM_KEY_TYPE_AES128);
		
			phKeyStore_SetKeyAtPos(pKeyStore, 0x00, 0x00, PH_CRYPTOSYM_KEY_TYPE_AES128,
					master_key, 0x00);
		
			status = phhalHw_SamAV3_Cmd_SAM_AuthenticateHost(
					&stHal_SamAv3,
					PHHAL_HW_SAMAV3_CMD_SAM_AUTHENTICATE_HOST_MODE_FULL,
					0,
					0,
					0,
					0
			);
			if(status){
				LOG2_ERR("phhalHw_SamAV3_Cmd_SAM_AuthenticateHost fail: %04X", status);
				break;
			}
		}
		break;
		case '3':{
			phKeyStore_Sw_DataParams_t * pKeyStore = phNfcLib_GetDataParams(PH_COMP_KEYSTORE);
			phStatus_t status;
			uint8_t master_key[16] = {0x01, };
			status = phKeyStore_FormatKeyEntry(pKeyStore, 0x00, PH_CRYPTOSYM_KEY_TYPE_AES128);
		
			phKeyStore_SetKeyAtPos(pKeyStore, 0x00, 0x00, PH_CRYPTOSYM_KEY_TYPE_AES128,
					master_key, 0x00);
		
			status = phhalHw_SamAV3_Cmd_SAM_AuthenticateHost(
					&stHal_SamAv3,
					PHHAL_HW_SAMAV3_CMD_SAM_AUTHENTICATE_HOST_MODE_FULL,
					0,
					0,
					0,
					0
			);
			if(status){
				LOG2_ERR("phhalHw_SamAV3_Cmd_SAM_AuthenticateHost fail: %04X", status);
				break;
			}
		}
		break;
		case '4':{
			for(kid = 0; kid < 0x10; kid++){
				memset(&key_entry_read, 0, sizeof(key_entry_read));
				ret = samav3_get_key_entry(kid, &key_entry_read);
				TEST_ASSERT_EQUAL_INT(0, ret);
				LOG2_INF("kid: %d", kid);
				samav3_print_key_entry_read(&key_entry_read);
			}

		}
		break;

		default:
			goto __exit;
		}

	}
__exit:
	//下电
	ret = samav3_deactivate();
	TEST_ASSERT_EQUAL_INT(0, ret);
}

#endif 

TEST(SAMAV3, key_manager)
{
	uint8_t kid = 0;
	int ret = samav3_init2();
	TEST_ASSERT_EQUAL_INT(0, ret);	
//		ret = samav3_activate();
//		TEST_ASSERT_EQUAL_INT(0, ret);	
	//读取密钥
	key_entry_read_t key_entry_read;

	while(1){
		LOG2_PRINT("wait key: \n");
		int input = SEGGER_RTT_WaitKey();
		LOG2_PRINT("input: %c\n", input);
		switch(input){
		case '0':{
			uint8_t sam_kids[] = {
				SAM_KID_KMR, SAM_KID_KMRM, SAM_KID_KMM, 
				SAM_KID_KCR, SAM_KID_KCRM, SAM_KID_KCM,
				SAM_KID_KUR, SAM_KID_KURM, SAM_KID_KUM, 
				SAM_KID_APPLE_PRIV, SAM_KID_APPLE_CRED, SAM_KID_GOOGLE
			};
			for(int i = 0; i < sizeof(sam_kids); i++){
				ret = samav3_disable_key_entry(sam_kids[i]);
				if(ret){
					LOG2_ERR("samav3_disable_key_entry fail: %04X", ret);
//						break;
				}
				ret = samav3_get_key_entry(sam_kids[i], &key_entry_read);
				if(ret){
					LOG2_ERR("samav3_get_key_entry fail: %04X", ret);
					break;
				}
				samav3_print_key_entry_read(&key_entry_read);
			}
		}
		break;
		case '1':{
			kid = 0x14;
			ret = samav3_get_key_entry(kid, &key_entry_read);
			if(ret){
				LOG2_ERR("samav3_get_key_entry fail: %04X", ret);
				break;
			}
			samav3_print_key_entry_read(&key_entry_read);
			ret = samav3_disable_key_entry(kid);
			if(ret){
				LOG2_ERR("samav3_disable_key_entry fail: %04X", ret);
				break;
			}
			ret = samav3_get_key_entry(kid, &key_entry_read);
			if(ret){
				LOG2_ERR("samav3_get_key_entry fail: %04X", ret);
				break;
			}
			samav3_print_key_entry_read(&key_entry_read);
		}
		break;

		case '4':{
			for(kid = 0x10; kid < 0x20; kid++){
				memset(&key_entry_read, 0, sizeof(key_entry_read));
				ret = samav3_get_key_entry(kid, &key_entry_read);
				TEST_ASSERT_EQUAL_INT(0, ret);
				LOG2_INF("kid: 0x%02X", kid);
				samav3_print_key_entry_read(&key_entry_read);
			}

		}
		break;
		default:
			goto __exit;
		}

	}
__exit:
	//下电
	ret = samav3_deactivate();
	TEST_ASSERT_EQUAL_INT(0, ret);
}



